package edu.washington.cs.workflow.analysis.guistructure.uievents;

import org.uispec4j.Key;
import org.uispec4j.Panel;
import org.uispec4j.Table;
import org.uispec4j.Trigger;
import org.uispec4j.UIComponent;
import org.uispec4j.Window;

import edu.washington.cs.workflow.analysis.guistructure.Spec4JUtils;
import edu.washington.cs.workflow.analysis.guistructure.uievents.UIEvent.WINDOW;
import edu.washington.cs.workflow.util.Utils;

public class TableEvent extends AbstractUIEvent  {

	public final Table table;
	public final UIAction action;
	public final int clickX;
	public final int clickY;
	public final String textToSet;
	
	TableEvent(Table table, Panel panel, UIAction action, int x, int y, String textToSet) {
		Utils.checkNotNull(table);
		Utils.checkNotNull(panel);
		Utils.checkNotNull(action);
		Utils.checkTrue(x >= 0, "illegal x: " + x);
		Utils.checkTrue(y >= 0, "illegal y: " + y);
		Utils.checkTrue(action.equals(UIAction.Click) || action.equals(UIAction.DoubleClick)
				|| action.equals(UIAction.RightClick) || action.equals(UIAction.SetText),
				"Illegal action: " + action);
		if(action.equals(UIAction.SetText)) {
			Utils.checkTrue(table.cellIsEditable(x, y).isTrue(),
					"Cell at (x, y): " + x + ", " + y + " is not editable.");
			Utils.checkNotNull(textToSet, "The text should not be null.");
		}
		this.textToSet = textToSet;
		this.table = table;
		this.action = action;
		this.setCurrentPanel(panel);
		this.clickX = x;
		this.clickY = y;
	}
	
	TableEvent(Table table, Panel panel, UIAction action, int x, int y) {
		this(table, panel, action, x, y, null);
	}
	
	@Override
	public UIComponent getUIComponent() {
		return this.table;
	}

	@Override
	public UIAction getAction() {
		return this.action;
	}
	
	@Override
	protected WINDOW probeWindowInfoInternal() {
		Trigger t = this.getTrigger();
		if(t == null && this.action.equals(UIAction.SetText)) {
			return WINDOW.NONE; //normally no window for setting text
		}
		WINDOW w = Spec4JUtils.getTriggeredDialog(this.table, t);
		Utils.checkNotNull(w);
		return w;
	}
	
	@Override
	public boolean canFireEvent() {
		return true;
	}

	@Override
	protected UIEventOutcome fireEventInternal() {
		WINDOW winStatus = null;
		if(super.getWindowFlag() == null) {
			winStatus = super.probeWindowInfo();
		} else {
			winStatus = super.getWindowFlag();
		}
		
		//XXX why check this?
	    Utils.checkTrue(!winStatus.equals(WINDOW.MODAL), "Wind status: " + winStatus); //XXX need to fix
	    
	    UIEventOutcome outcome = new UIEventOutcome();
	    if(!action.equals(UIAction.SetText)) { //for setting text, there is no
	        outcome.setTrigger(this.getTrigger());
	    }
	    
	    if(winStatus.equals(WINDOW.NONMODAL)) {
	    	outcome.setWindowStatus(winStatus);
	    	return outcome;
	    }
	    
	    Throwable error = null;
	    //if no dialog has popped up
	    try {
	    	if(this.action.equals(UIAction.Click)) {
				this.table.click(clickX, clickY);
			} else if (this.action.equals(UIAction.DoubleClick)) {
				this.table.doubleClick(clickX, clickY);
			} else if (this.action.equals(UIAction.RightClick)) {
				this.table.rightClick(clickX, clickY);
			} else if (this.action.equals(UIAction.SetText)) {
				this.table.editCell(clickX, clickY, this.textToSet, true);
			}
		} catch (Throwable e) {
//		  System.err.println("windows status: " + winStatus);
		  error = e;
//		  e.printStackTrace();
//		  System.exit(1);
		}
			
		if(error != null) {
		   outcome.setError(error);
		}
		outcome.setWindowStatus(winStatus);
		outcome.currentPanelClosed(super.isCurrentPanelClosed());
		
		return outcome;
	}
	
	protected Trigger getTrigger() {
		if(this.action.equals(UIAction.Click)) {
			return this.table.triggerClick(this.clickX, this.clickY, Key.Modifier.NONE);
		} else if (this.action.equals(UIAction.DoubleClick)) {
			return this.table.triggerDoubleClick(this.clickX, this.clickY);
		} else if (this.action.equals(UIAction.RightClick)) {
//			System.out.println("Right click: " + this.clickX + ",  " + this.clickY);
			return this.table.triggerRightClick(this.clickX, this.clickY);
		} else if (this.action.equals(UIAction.SetText)) {
			return null; //no trigger for setting text
		} else {
			return null;
		}
	}
	
	@Override
	public String toString() {
		String title = "";
		if(this.getCurrentPanel() instanceof Window) {
			title = ((Window)this.getCurrentPanel()).getTitle();
		}
		return this.action + " table: " + this.table.getLabel() + "at x: " + this.clickX + ", y: " + this.clickY
		 + ", at panel: " + this.getCurrentPanel().getLabel()
		 + ",  " + this.getCurrentPanel() + ", title: " + title + ", table size: " + this.table.getRowCount()
		 + ", " + this.table.getColumnCount();
	}

	@Override
	public String getDescription() {
		String title = "";
		if(this.getCurrentPanel() instanceof Window) {
			title = ((Window)this.getCurrentPanel()).getTitle();
		}
		return this.action + " table: " + this.table.getLabel()
		 + ", at panel: " + this.getCurrentPanel().getLabel()
		 + ",  " + this.getCurrentPanel() + ", title: " + title;
	}
}
